package logger

import (
	"errors"
	"os"
	"path/filepath"
	"strings"
	"sync/atomic"

	"gitee.com/gousing/helper/files"
	"gopkg.in/natefinch/lumberjack.v2"
)

type FileOptions struct {
	MaxSize    int    // 文件最大尺寸（以MB为单位）, 默认 2
	MaxBackups int    // 保留的最大旧文件数量，  默认 15
	MaxAge     int    // 保留旧文件的最大天数，默认 30
	Compress   bool   // 是否压缩/归档旧文件，默认 false
	LocalTime  bool   // 使用本地时间创建时间戳，默认 true
	SavePath   string // 日志文件存放的位置, 基于WorkPath工作目录, 默认为"logs"
}

const (
	defaultMaxSize    int    = 2
	defaultMaxBackups int    = 15
	defaultMaxAge     int    = 30
	defaultCompress   bool   = false
	defaultLocalTime  bool   = true
	defaultSavePath   string = "logs"
)

// NewFileStorage 依据文件名及选项创建Lumberjack文件实例 ( 通过 lumberjack 管理日志文件的写入及滚动 )
//   - fileName 是绝对路径文件时不和SavePath进行拼装, 否则自动拼装日志文件完整路径(options.SavePath/fileName)
func NewFileStorage(fileName string, options *FileOptions) (Storager, error) {
	fileName = strings.TrimSpace(fileName)
	if fileName == "" {
		return nil, errors.New("NewStorageFile, fileName is empty")
	}
	op := FileOptions{
		MaxSize:    defaultMaxSize,    // 文件最大尺寸（以MB为单位）
		MaxBackups: defaultMaxBackups, // 保留的最大旧文件数量
		MaxAge:     defaultMaxAge,     // 保留旧文件的最大天数
		Compress:   defaultCompress,   // 是否压缩/归档旧文件
		LocalTime:  defaultLocalTime,  // 使用本地时间创建时间戳
		SavePath:   defaultSavePath,   // 日志文件的位置, 基于WorkPath工作目录, 默认为"logs"
	}
	if options != nil {
		if options.MaxSize > 0 {
			op.MaxSize = options.MaxSize
		}
		if options.MaxBackups > 0 {
			op.MaxBackups = options.MaxBackups
		}
		if options.MaxAge > 0 {
			op.MaxAge = options.MaxAge
		}
		op.Compress = options.Compress
		op.LocalTime = options.LocalTime
		if op.SavePath != "" {
			op.SavePath = options.SavePath
		}
	}
	op.SavePath = files.FolderToPath(op.SavePath)
	if err := files.PathCreateIfNotExist(op.SavePath, os.FileMode(0777)); err != nil {
		return nil, errors.New("NewStorageFile, savePath[" + op.SavePath + "] " + err.Error())
	}
	// fileName 不是绝对路径文件
	if !filepath.IsAbs(fileName) {
		// 依据自动拼装日志文件完整路径(SavePath/fileName)
		fileName = filepath.Clean(op.SavePath + "/" + fileName)
	}
	writer := &lumberjack.Logger{
		Filename:   fileName,      // 日志文件的位置
		MaxSize:    op.MaxSize,    // 文件最大尺寸（以MB为单位）
		MaxBackups: op.MaxBackups, // 保留的最大旧文件数量
		MaxAge:     op.MaxAge,     // 保留旧文件的最大天数
		Compress:   op.Compress,   // 是否压缩/归档旧文件
		LocalTime:  op.LocalTime,  // 使用本地时间创建时间戳
	}
	return &storage{
		writer:       writer,
		closed:       new(atomic.Bool),
		isLumberjack: true,
		isCloser:     true,
	}, nil
}
